var gamejs = require("gamejs");
var Sprite = require("gamejs/sprite").Sprite;
var radarModule = require("js/radar");
var obstacleModule = require("js/obstacle");
var turretModule = require("js/turret");
var loadingNightSceneModule = require("js/scenes/loadingNightScene");
var storeSceneModule = require("js/scenes/storeScene");
var pauseSceneModule = require("js/scenes/pauseScene");

/**
 * DayScene, the scene where player can build radars, turrets and obstacles.
 */

/**
 * Creates a DayScene object, here the player can modify the map.
 * 
 * @param {ScenesDirector} director The ScenesDirector object that directs the game.
 * @param {Match} match The Match object representing the game.
 * 
 * @constructor
 */
var DayScene = exports.DayScene = function(director, match) {
	this.director = director;
	this.match = match;
	this.selectedItem = null;
	this.toPlaceItem = null;
	this.timer = DAY_TIME;
	this.font = new gamejs.font.Font("15px Verdana");
	
	//just to try code
	this.radarPlaced = false;
	this.turretPlaced = false;
	
	//HUD background image
	this.hudBackground = gamejs.image.load(imgPath + "hudBackground.png");
	
	//pause image
	this.pause = new Sprite();
	this.pause.image = gamejs.image.load(imgPath + "pause.png");
	this.pause.rect = new gamejs.Rect([5, 5], this.pause.image.getSize());
	
	//to night image
	this.disabledToNight = gamejs.image.load(imgPath + "disabledToNight.png");
	this.enabledToNight = gamejs.image.load(imgPath + "toNight.png");
	this.canToNight = false;
	this.toNight = new Sprite();
	this.toNight.image = this.disabledToNight;
	this.toNight.rect = new gamejs.Rect([10, 90], this.toNight.image.getSize());
	
	//build image
	this.build = new Sprite();
	this.build.image = gamejs.image.load(imgPath + "build.png");
	this.build.rect = new gamejs.Rect([10, 160], this.build.image.getSize());
	
	//sell image
	this.disabledSell = gamejs.image.load(imgPath + "disabledSell.png");
	this.enabledSell = gamejs.image.load(imgPath + "sell.png");
	this.canSell = false;
	this.sell = new Sprite();
	this.sell.image = this.disabledSell;
	this.sell.rect = new gamejs.Rect([10, 240], this.sell.image.getSize());
	
	//upgrade image
	this.disabledUpgrade = gamejs.image.load(imgPath + "disabledUpgrade.png");
	this.enabledUpgrade = gamejs.image.load(imgPath + "upgrade.png");
	this.canUpgrade = false;
	this.upgrade = new Sprite();
	this.upgrade.image = this.disabledUpgrade;
	this.upgrade.rect = new gamejs.Rect([10, 320], this.upgrade.image.getSize());
	
	//info image
	this.disabledShowInfo = gamejs.image.load(imgPath + "disabledShowInfo.png");
	this.enabledShowInfo = gamejs.image.load(imgPath + "showInfo.png");
	this.canInfo = false;
	this.showInfo = new Sprite();
	this.showInfo.image = this.disabledShowInfo;
	this.showInfo.rect = new gamejs.Rect([10, 400], this.showInfo.image.getSize());
};

/**
 * Resets the timer to the start value. 
 */
DayScene.prototype.resetTimer = function() {
	this.timer = DAY_TIME;
};

/**
 * Takes an item so the player can place it in the map.
 * 
 * @param {Object} item The item that the player have to place.
 * The given item must have this properties:
 * -image : the image to draw before it is placed;
 * -topLeft : the position where to draw the image;
 * -type : the item constructor.
 * Depending on the type property, the item must have some other properties:
 * -radius(if type is Obstacle) : the radius of the obstacle;
 */
DayScene.prototype.setToPlaceItem = function(item) {
	this.toPlaceItem = item;
};

/**
 * Updates the scene and its contents, managing the various events.
 * 
 * @param {number} msDuration The time past from the last call, in ms.
 */
DayScene.prototype.update = function(msDuration) {
	//updates the match and everything else in cascade
	this.match.update(msDuration);
	
	this.timer -= msDuration;
	
	if(this.timer <= 0) {
		this.director.pushScene(new loadingNightSceneModule.LoadingNightScene(this.director, this.match));
		return;
	}
	
	var events = gamejs.event.get();
	
	for ( i = 0; i < events.length; i++) {
		var currentEvent = events[i];
		if(this.toPlaceItem != null) {
			//there's an object to place in the map
			var dim = this.toPlaceItem.image.getSize();
			if(currentEvent.type == gamejs.event.MOUSE_MOTION) {
				//move the pictures
				var newPos = currentEvent.pos;
				var topleft = [newPos[X] - dim[WIDTH] / 2, newPos[Y] - dim[HEIGHT] / 2];
				
				//avoid invalid positions
				if(topleft[X] < WIDTH_OFFSET) {
					topleft[X] = WIDTH_OFFSET;
				}
				if(topleft[X] >= (WIDTH_OFFSET + MAP_WIDTH - dim[WIDTH])) {
					topleft[X] = (WIDTH_OFFSET + MAP_WIDTH - dim[WIDTH]) - 1;
				}
				if(topleft[Y] < HEIGHT_OFFSET) {
					topleft[Y] = HEIGHT_OFFSET;
				}
				if(topleft[Y] >= (HEIGHT_OFFSET + MAP_HEIGHT - dim[HEIGHT])) {
					topleft[Y] = (HEIGHT_OFFSET + MAP_HEIGHT - dim[HEIGHT]) - 1;
				}
				
				this.toPlaceItem.topLeft = topleft;
				continue;//go to the next event
			}
			
			if(currentEvent.type == gamejs.event.MOUSE_UP) {
				//add the item to the map
				var point = currentEvent.pos;
				
				//manage boundary click
				if(point[X] < (WIDTH_OFFSET + dim[WIDTH] / 2)) {
					point[X] = (WIDTH_OFFSET + dim[WIDTH] / 2);
				}
				if(point[X] >= (WIDTH_OFFSET + MAP_WIDTH - dim[WIDTH] / 2)) {
					point[X] = (WIDTH_OFFSET + MAP_WIDTH - dim[WIDTH] / 2) - 1;
				}
				if(point[Y] < (HEIGHT_OFFSET + dim[HEIGHT] / 2)) {
					point[Y] = (HEIGHT_OFFSET + dim[HEIGHT] / 2);
				}
				if(point[Y] >= (HEIGHT_OFFSET + MAP_HEIGHT - dim[HEIGHT] / 2)) {
					point[Y] = (HEIGHT_OFFSET + MAP_HEIGHT - dim[HEIGHT] / 2) - 1;
				}
				
				var actualPoint = [point[X] - WIDTH_OFFSET, point[Y] - HEIGHT_OFFSET];
				var itemType = this.toPlaceItem.type;
				var radius = this.toPlaceItem.radius;
				this.toPlaceItem = null;
				
				if(itemType == "radar") {
					//it's a radar
					this.match.getMap().addRadar(new radarModule.Radar(this.match, actualPoint));
					break;
				}

				if(itemType == "turret") {
					//it's a turret
					this.match.getMap().addTurret(new turretModule.Turret(this.match, actualPoint));
					break;
				}
				
				if(itemType == "obstacle") {
					//it's an obstacle
					this.match.getMap().addObstacle(new obstacleModule.Obstacle(this.match, actualPoint, radius));
					break;
				}
				
				throw new Error("Can't trigger this type");
			}
		}

		//process only one valid mouse click(this is the cause of the break statements)
		if (currentEvent.type == gamejs.event.MOUSE_UP) {
			var point = currentEvent.pos;
			if (this.pause.rect.collidePoint(point)) {
				//click on pause
				this.selectedItem = null;
				this.director.pushScene(new pauseSceneModule.PauseScene(this.director, this.match));
				//no break statement because selectedItem is changed,
				//need to update
			}
			
			if (this.canToNight && this.toNight.rect.collidePoint(point)) {
				//click on to night
				this.director.pushScene(new loadingNightSceneModule.LoadingNightScene(this.director, this.match));
				break;
			}
			
			if (this.build.rect.collidePoint(point)) {
				//click on build
				this.selectedItem = null;
				this.director.pushScene(new storeSceneModule.StoreScene(this.director, this.match));
				//no break statement because selectedItem is changed,
				//need to update
			}

			//there's an object selected
			if(this.selectedItem != null) {
				if (this.canSell && this.sell.rect.collidePoint(point)) {
					//click on sell
					this.selectedItem.sell();
					this.selectedItem = null;//item sold
					//no break statement because selectedItem is changed,
					//need to update
				}
				
				if (this.canUpgrade && this.upgrade.rect.collidePoint(point)) {
					//click on upgrade
					this.selectedItem.upgrade();
					//no break statement because selectedItem is changed,
					//need to update
				}
				
				if (this.canShowInfo && this.showInfo.rect.collidePoint(point)) {
					//click on show info
					this.director.pushScene(new InfoScene(this.director, this.selectedItem));
					break;
				}
			}

			//checks if the click is on an item of the map
			var mapPoint = [point[X] - WIDTH_OFFSET, point[Y] - HEIGHT_OFFSET];
			var selRadars = this.match.getMap().getRadars().collidePoint(mapPoint);
			var selTurrets = this.match.getMap().getTurrets().collidePoint(mapPoint);
			var selObstacles = this.match.getMap().getObstacles().collidePoint(mapPoint);
			var numSelected = selRadars.length + selTurrets.length + selObstacles.length;
			if(numSelected == 1) {
				//there is just one item selected
				if(selRadars[0]) {
					this.selectedItem = selRadars[0];
				}
				
				if(selTurrets[0]) {
					this.selectedItem = selTurrets[0];
				}
				
				if(selObstacles[0]) {
					this.selectedItem = selObstacles[0];
				}
			}
			else {
				//there are zero or more than one items selected
				this.selectedItem = null;//selection not valid
			}
			
			//if an item is selected, checks if it can be upgraded, sold
			//or has some info to show
			if(this.selectedItem != null) {
				if(this.selectedItem.upgrade && this.selectedItem.canUpgrade()) {
					this.canUpgrade = true;
				}
				else {
					this.canUpgrade = false;
				}
				
				if(this.selectedItem.sell && this.selectedItem.getSaleable()) {
					this.canSell = true;
				}
				else {
					this.canSell = false;
				}
				
				if(this.selectedItem.getInfo) {
					this.canShowInfo = true;
				}
				else {
					this.canShowInfo = false;
				}
			}
			else {
				//nothing selected
				this.canUpgrade = false;
				this.canSell = false;
				this.canShowInfo = false;
			}
		}
	}
	
	//checks if can go to night(need a radar and a turret)
	var radarPlaced = this.match.getMap().hasRadars();
	var turretPlaced = this.match.getMap().hasTurrets();
	this.canToNight = (radarPlaced && turretPlaced);
	
	//sets the correct image(enabled/disabled)
	this.toNight.image = this.canToNight ? this.enabledToNight : this.disabledToNight;
	this.sell.image = this.canSell ? this.enabledSell : this.disabledSell;
	this.upgrade.image = this.canUpgrade ? this.enabledUpgrade : this.disabledUpgrade;
	this.showInfo.image = this.canShowInfo ? this.enabledShowInfo : this.disabledShowInfo;
};

/**
 * Draws the scene and its contents in the director Surface.
 */
DayScene.prototype.draw = function() {
	var surface = this.director.getSurface();
	surface.blit(this.hudBackground);
	this.pause.draw(surface);
	this.toNight.draw(surface);
	this.build.draw(surface);
	this.sell.draw(surface);
	this.upgrade.draw(surface);
	this.showInfo.draw(surface);
	//draws the match(health, credits and score) and everything else
	//(the map) in cascade
	this.match.draw(surface);
	
	//draws the item to place, if any
	if(this.toPlaceItem != null) {
		surface.blit(this.toPlaceItem.image, this.toPlaceItem.topLeft);
	}
	
	//writes the remaining time
	surface.blit(this.font.render((this.timer / 1000).toFixed(1), "#FF0000"), [20, 70]);
	
	if(this.canSell) {
		//writes the credits received if the selected item will sold
		surface.blit(this.font.render(this.selectedItem.getResaleValue(), "#82E0FF"), [35, 290]);
	}
	
	if(this.canUpgrade) {
		//writes the credits needed to upgrade the selected item
		surface.blit(this.font.render(this.selectedItem.priceToUpgrade(), "#82E0FF"), [35, 370]);
	}
};